#include "stdafx.h"
#include "ObjectManager.h"
#include "Objects.h"
//#include "MapCreator.h"
//#include "Enemies.h"
#include "Bullets.h"
#include "Game.h"
#include "MathFunctions.h"
#include "LevelManager.h"
#include "Player.h"

COBJManager* COBJManager::m_pInstance = NULL;

COBJManager* COBJManager::GetInstance()
{
	if(!m_pInstance)
		m_pInstance = new COBJManager();

	return m_pInstance;
}

void COBJManager::Update(float fDeltaTime)
{
	//Bullets update
	unsigned int counter = this->m_vBullets.size();
	for(unsigned int i = 0; i < counter; ++i)
	{
		this->m_vBullets[i]->Update(fDeltaTime);
		if(this->m_vBullets[i]->GetLife() <= 0.0f)
		{
			this->m_vBullets[i]->DestroyBullet();
			this->m_vBullets.erase(m_vBullets.begin() + i);

			//Reduce counter by one and i by 1
			counter -= 1;
			i -= 1;
		}
	}

	counter = this->m_vEnemyBullets.size();
	for(unsigned int i = 0; i < counter; i += 1)
	{
		this->m_vEnemyBullets[i]->Update(fDeltaTime);
		if(this->m_vEnemyBullets[i]->GetLife() <= 0.0f)
		{
			this->m_vEnemyBullets[i]->DestroyBullet();
			this->m_vEnemyBullets.erase(m_vEnemyBullets.begin() + i);

			counter -= 1;
			i -= 1;
		}
	}

	//Enemy Updates
	counter = this->m_vEnemies.size();
	for(unsigned int i = 0; i < counter; i += 1)
	{
//		this->m_vEnemies[i]->Update(fDeltaTime);
	}

	//Check Collisions
	this->CheckCollisions();
}

void COBJManager::Render(void)
{
	glClear(GL_DEPTH_BUFFER_BIT);

	//Render start
	glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);

	//AABB's
	unsigned int counter = 0;
	counter = this->m_vAABBs.size();

	for(unsigned int i = 0; i < counter; i++)
	{
		glDisable(GL_LIGHTING);
		glEnable(GL_NORMALIZE);
		glShadeModel(GL_SMOOTH);
		this->GetAColor(i);
		this->m_vAABBs[i]->Render();
		glDisable(GL_LIGHTING);
	}

	counter = this->m_vCylinders.size();

	for(unsigned int i = 0; i < counter; i++)
	{
		glPushMatrix();
			glTranslatef(this->m_vCylinders[i]->m_vBaseCenter.x, this->m_vCylinders[i]->m_vBaseCenter.y, this->m_vCylinders[i]->m_vBaseCenter.z);
			glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
			this->m_vCylinders[i]->Render(); 
		glPopMatrix();
	}

	//Enemies
	glColor3f(1.0f, 0.0f, 0.0f);
	counter = this->m_vEnemies.size();
	for(unsigned int i = 0; i < counter; i++)
	{
//		this->m_vEnemies[i]->Render();
	}

	//Bullets
	glColor3f(0.0f, 0.0f, 1.0f);
	counter = this->m_vBullets.size();
	for(unsigned int i = 0; i < counter; ++i)
	{
		this->m_vBullets[i]->Render();
	}

	counter = this->m_vEnemyBullets.size();
	for(unsigned int i = 0; i < counter; i += 1)
	{
		this->m_vEnemyBullets[i]->Render();
	}
}

void COBJManager::CreateObjects()
{
	//empty vectors
	this->m_vAABBs.clear();
	this->m_vCylinders.clear();

	this->m_pLevel = CLevelManager::GetInstance();
	this->m_pLevel->Init();
	this->m_pLevel->LoadLevel();
}

void COBJManager::CheckCollisions()
{
	//Temp variables
	vec3f start, end;
	AABB* temp;

	//Bullets - Enemies
/*	for(unsigned int i = 0; i < m_vBullets.size(); i += 1)
	{
		//Enemies
		for(unsigned int j = 0; j < m_vEnemies.size(); j += 1)
		{
			//Create vectors
			vec3f d; 
			d.x = m_vBullets[i]->GetCollision()->m_vCenter.x - m_vEnemies[j]->GetBounds()->m_vCenter.x;
			d.y = m_vBullets[i]->GetCollision()->m_vCenter.y - m_vEnemies[j]->GetBounds()->m_vCenter.y;
			d.z = m_vBullets[i]->GetCollision()->m_vCenter.z - m_vEnemies[j]->GetBounds()->m_vCenter.z;

			float dDot = dot_product(d,d);
			float r1 = m_vBullets[i]->GetCollision()->m_fRadius;
			float r2 = m_vEnemies[j]->GetBounds()->m_fRadius;
			if(dDot <= ((r1+r2)*(r1+r2)))
			{
				//Collision occurred
				m_vEnemies[j]->SetHealth(m_vEnemies[j]->GetHealth() - m_vBullets[i]->GetDamage());

				//Remove Bullet
				this->m_vBullets[i]->DestroyBullet();
				this->m_vBullets.erase(m_vBullets.begin() + i);
				i -= 1;

				//Check Enemy Health
				if(m_vEnemies[j]->GetHealth() <= 0)
				{
					//Enemy Dead
					this->m_vEnemies[j]->Destroy();
					this->m_vEnemies.erase(m_vEnemies.begin() + j);
				}

				//Break to initial loop
				break;
			}
		}

		//Walls
		for(unsigned int j = 0; j < m_vAABBs.size(); ++j)
		{

		}
	}
*/
	//Temp variables for wall collisions
	vec3f min, max; min.make_zero(); max.make_zero();
	//Camera Position
	vec3f pos; pos = CPlayer::GetInstance()->GetPlayerPosition();
	start = CGame::GetInstance()->GetPreviousPos();

	//Wall test variables
	Plane p; vec3f CP; int nDepth = 0; vec3f Stored = start;

	//Player to walls, using a temporary radius of 1.0f
	for(unsigned int i = 0; i < m_vAABBs.size(); i += 1)
	{
		if(nDepth > 2)
		{
			//Set position to start position
			CGame::GetInstance()->SetPlayerPos(start);
			break;
		}

		if(m_vAABBs[i]->m_bChecked)
			continue;

		//Adjusted Box
		AABB* temp; temp = m_vAABBs[i];

		//Check to see if the line segment intersects with any of the boxe's walls
		if(SegmentToBoxIntersection(start, pos, temp, p, CP, 0.5f))
		{
			//Handle Sliding, for now redundant but make it work, then optimize.
			this->HandleWallSlide(p, CP, pos);
			
			//Reset to check
			nDepth += 1; pos = CPlayer::GetInstance()->GetPlayerPosition();
		}
	}
}

void COBJManager::HandleWallSlide(Plane p, vec3f CP, vec3f vEnd)
{
	vec3f vTo = CP;	vTo = vTo - vEnd;
	float length = dot_product(vTo, p.m_vNormal);
	vec3f scaled = p.m_vNormal; scaled.scale(length);
	vec3f vMoveTo; vMoveTo = vEnd + scaled;
	
	CPlayer::GetInstance()->SetOrigin(vMoveTo);
}

void COBJManager::GetAColor(unsigned int i)
{
	int myCase = i%6;

	switch(myCase)
	{
		case 1:
		{
			glColor3f(1.0f, 0.0f, 0.0f);
			break;
		}
		case 2:
		{
			glColor3f(1.0f, 1.0f, 0.0f);
			break;
		}
		case 3:
		{
			glColor3f(1.0f, 0.0f, 1.0f);
			break;
		}
		case 4:
		{
			glColor3f(0.0f, 1.0f, 0.0f);
			break;
		}
		case 5:
		{
			glColor3f(0.0f, 1.0f, 1.0f);
			break;
		}
		default:
		{
			glColor3f(0.5f, 0.5f, 0.5f);
			break;
		}




		
	}
}